Android Tips #28 Android 1.6 から Fragment を使う
はじめに
Fragment は Android 3.0 (APIレベル11) から導入されたコンポーネントです。Fragment は Support Package でサポートされているので Android 1.6 (APIレベル4) から使用することができます。ということで今回は Android 1.6 〜 2.3 くらいまでをターゲットに開発してきた方々を対象に、 Fragment についての概要、そして Support Package を使って Fragment を使うにはどうすればよいか解説したいと思います!
Fragment とは?
Activity を機能・振る舞いごとに分割できる!
Fragment は Activity を 機能・振る舞いごとに分割するための UI モジュールです。Fragment を用いることで Activity の UI を簡単に分割して構成することができます。動的な追加や削除が容易にでき、また複数の画面に同じ Fragment を配置できたりします。ライフサイクルを持っているので、小さな Activity と捉えても良いかも知れません。
こういったときに便利です!
画面を構成する部位ごとを Fragment としてモジュール化すれば、画面サイズに応じたレイアウトがしやすくなります。例えば下図のように「タブレットでは一画面、スマホ (Handset) では二画面にする」というレイアウトにしたい場合、レイアウトを Fragment に分割してあげればレイアウトをゴリゴリいじる必要もなく実装できますし、またさらに他の画面に使い回すこともできます。多画面に対応するアプリを作りたい場合 Fragment はもはや必須!ですね!
Fragment を Activity で使う
ということで Support Package の Fragment クラスを使ってみたいと思います。
レイアウトXMLで追加する
1. カスタム Fragment を作成する
まずは Fragment のレイアウトを XML で適当に作成します。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" android:background="#eeeeee" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:text="Hello, SupportFragment!" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> </LinearLayout>
次に Fragment クラスを自作します。親クラスは android.support.v4.app.Fragment を使います。android.app.Fragment ではないので注意しましょう!
onCreateView() メソッドをオーバーライドし、渡される LayoutInflator クラスを使って先ほどのレイアウトを View にします。
package jp.classmethod.android.sample.supportpackage.fragment; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MainFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_main, container, false); } }
これで Fragment ができました!
2. FragmentActivity を継承した Activity を作る
次に作成した Fragment を Activity に追加します。レイアウトXML で fragment タグを使ってレイアウトに追加します。class 要素に 先ほど作成した Fragment のクラス名を入れます。
<fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment" android:layout_width="match_parent" android:layout_height="match_parent" class="jp.classmethod.android.sample.supportpackage.fragment.MainFragment" />
次に Activity クラスを作ります。Fragment を取り扱う Activity クラスは FragmentActivity を継承しなければなりません。あとは普通に setContentView() して終わりです。
package jp.classmethod.android.sample.supportpackage.fragment; import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
無事に Android 1.6 で Fragment が表示できました!
FragmentManager で動的に追加する
FragmentManager クラスを使うと、 Fragment を Java から動的に追加することができます!
1. Fragment を作る
レイアウトXMLで追加したときと同様、まずは Fragment を作ります。
2. FragmentActivity を継承した Activity を作る
ここも先ほどと同様に FragmentActivity を継承した Activity を作ります。今回は動的に追加したいので、レイアウトXMLに fragment タグは書きません。以下のように Fragment を追加する View (LinearLayout) を配置しておきます。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/layout_a" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical" android:background="#ff0000" /> <LinearLayout android:id="@+id/layout_b" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical" android:background="#00ff00" /> </LinearLayout>
3. FragmentManager と FragmentTransaction を呼び出す
次に onCreate() で Fragment を管理する FragmentManager クラスを呼び出します。FragmentActivity#getSupportFragmentManager() で呼び出します。このとき android.support.v4.app.FragmentManager クラスを使うようにしないと Android 1.6 では動作しないので注意が必要です。
FragmentManager manager = getSupportFragmentManager();
次に FragmentManager#beginTransaction() で FragmentTransaction クラスを呼び出します。FragmentTransaction は Fragment の追加や削除などを1つの処理としてまとめるためのトランザクションクラスです。
FragmentTransaction tx = manager.beginTransaction();
4. Fragment をスタックに追加する
FragmentTransaction#add() を使って Fragment を追加します。追加先の View の ID を指定すると、その対象の View に Fragment が追加されます。また Fragment にはタグを付けることができます。add() したときに既にバックスタックに同じタグの Fragment が存在する場合、Fragment は新規作成されず、既にインスタンス化してある Fragment が再表示されます。最後に commit() すると操作内容が反映されます。
tx.add(R.id.layout_a, new MainFragment(), "fragment_a"); tx.add(R.id.layout_b, new MainFragment(), "fragment_b"); tx.commit();
実行すると、2つの LinearLayout にそれぞれ同じ Fragment が配置されます!
サンプルソース
サンプルソースを github で公開しました!ソース自体たいした量はありませんが、ぜひ参考にしてください♪
suwa-yuki/SupportFragmentSample
まとめ
Fragment は画面が複雑になればなるほど便利に働く気がします。最新 SDK バージョンでは Fragment の中に Fragment をネストできるようになったので、さらに機能的になってます(SupportPackageでもサポートされています!)。とっても便利なのでぜひ覚えて使いましょう! サブクラスに DialogFragment や ListFragment などもあるので、こちらは次回以降に解説したいと思います。